/**
 * Octopus, an XMMS2 client.
 * Copyright (C) 2014 Octopus Team
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

namespace Octopus {
	public class CollectionAlbum : MedialibTracklist, IMedialibInfo {
		public Xmms.Value collectioninfo { get; construct; }

		public CollectionAlbum (string name, Xmms.Value collectioninfo) {
			Object (name: name, collectioninfo: collectioninfo);
		}

		construct {
			string album;
			string artist;
			int    partofset;
			string performer;
			string picture_front;

			collectioninfo.dict_entry_get_string ("album", out album);
			if (album != null) this.album = album;
			collectioninfo.dict_entry_get_string ("artist", out artist);
			if (artist != null) this.artist = artist;
			collectioninfo.dict_entry_get_int    ("partofset", out partofset);
			this.partofset = partofset;
			collectioninfo.dict_entry_get_string ("performer", out performer);
			if (performer != null) this.performer = performer;
			collectioninfo.dict_entry_get_string ("picture_front", out picture_front);
			if (picture_front != null) this.picture_front = picture_front;
			this.stored_in_medialib = true;
		}

		public void request_data () {
			add (this);
			add_finished ();
		}

		public string get_artist_performer () {
			if (performer != "") {
				return performer;
			}
			return artist;
		}

		public string get_album_partofset () {
			if (partofset == 0) {
				return album;
			} else {
				return album + " (" + "%d".printf (partofset) + ")";
			}
		}
	}

	public class CollectionNoGroup : MedialibTracklist, IMedialibInfo {
		public signal void rename_finished (string name);
		private string _new_name;

		public CollectionNoGroup () {
			Object ();
		}

		construct {
			this.stored_in_medialib = true;
		}

		public void request_data () {
			add (this);
			add_finished ();
		}

		public void xmms_collection_rename (string new_name) {
			_new_name = new_name;
			Global.get ().get_xmms_client ().get_xmms ().coll_rename (name, new_name, Xmms.COLLECTION_NS_COLLECTIONS).notifier_set ((val) => {
				if (val.is_error ()) {
					unowned string error;
					if (val.get_error(out error)) {
						Global.get ().message ("error: %s".printf (error));
						GLib.warning ("error renaming collection: %s", error);
					}
					rename_finished (name);
				}
				name = _new_name;
				rename_finished (_new_name);
				return true;
			});
		}

		public void xmms_collection_create (string new_name) {
			Xmms.Collection collection;
			Xmms.Collection.parse (searchquery, out collection);
			Global.get ().get_xmms_client ().get_xmms ().coll_save (collection, new_name, Xmms.COLLECTION_NS_COLLECTIONS).notifier_set ((val) => {
				if (val.is_error ()) {
					unowned string error;
					if (val.get_error(out error)) {
						Global.get ().message ("error: %s".printf (error));
						GLib.warning ("error creating collection: %s", error);
					}
				}
				stored_in_medialib = true;
				return true;
			});
		}

	}

	public class CollectionGroupedByAlbum : Object, IMedialibInfo, IComparable, ICollection {
		public signal void rename_finished (string name);
		private string _new_name;
		public string name { get; construct set; default = ""; }
		public string searchquery { get; set; default = ""; }
		public bool stored_in_medialib { get; set; default = true; }

		public CollectionGroupedByAlbum (string name) {
			Object (name: name);
		}

		public string get_compare_string () {
			return name;
		}

		public string get_namespace () {
			return Xmms.COLLECTION_NS_COLLECTIONS;
		}

		public void request_data () {
			Xmms.Collection collection;
			if (searchquery != "") {
				Xmms.Collection.parse (searchquery, out collection);
			} else {
				Xmms.Collection.parse ("in:\"" + name + "\"", out collection);
			}

			var order = new Xmms.Value.from_list ();
			order.list_append (new Xmms.Value.from_string ("album"));
			order.list_append (new Xmms.Value.from_string ("artist"));
			order.list_append (new Xmms.Value.from_string ("partofset"));
			order.list_append (new Xmms.Value.from_string ("performer"));
			order.list_append (new Xmms.Value.from_string ("picture_front"));
			var fetch = new Xmms.Value.from_list ();
			fetch.list_append (new Xmms.Value.from_string ("album"));
			fetch.list_append (new Xmms.Value.from_string ("artist"));
			fetch.list_append (new Xmms.Value.from_string ("partofset")); //used for multi-cds
			fetch.list_append (new Xmms.Value.from_string ("performer")); //used for compilations
			fetch.list_append (new Xmms.Value.from_string ("picture_front"));
			var group = new Xmms.Value.from_list ();
			group.list_append (new Xmms.Value.from_string ("album"));
			group.list_append (new Xmms.Value.from_string ("picture_front"));
			group.list_append (new Xmms.Value.from_string ("partofset"));

			Global.get ().get_xmms_client ().get_xmms ().coll_query_infos (
			  collection, //Collection coll
			  order,      //Xmms.Value order
			  0,          //uint limit_start = 0
			  0,          //uint limit_len = 0
			  fetch,      //Xmms.Value? fetch = null
			  group       //Xmms.Value? group = null
			  ).notifier_set (on_coll_query_albumList);
		}

		private bool on_coll_query_albumList(Xmms.Value values) {
			unowned Xmms.ListIter iter;

			if (values.is_error()) {
				unowned string error = "unknown";
				values.get_error(out error);
				GLib.warning ("warning, failed to query (%s)", error);
				return true;
			}

			values.get_list_iter(out iter);
			if (!iter.valid()) {
				var emptyCollection = new CollectionNoGroup ();
				emptyCollection.name = name;
				emptyCollection.searchquery = searchquery;
				emptyCollection.stored_in_medialib = stored_in_medialib;
				add (emptyCollection);
				add_finished (); //empty iterator; no query result
			}

			for (iter.first(); iter.valid(); iter.next()) {
				unowned Xmms.Value entry;

				iter.entry(out entry);

				CollectionAlbum e = new CollectionAlbum (name, entry);
				e.stored_in_medialib = stored_in_medialib;
				if (searchquery != "") {
					e.searchquery = _searchquery;
				}
				add (e);
			}
			add_finished ();
			return true;
		}

		public void xmms_collection_remove () { 
			Global.get ().get_xmms_client ().get_xmms ().coll_remove (name, Xmms.COLLECTION_NS_COLLECTIONS);
		}

		public void xmms_collection_rename (string new_name) {
			_new_name =  new_name;
			Global.get ().get_xmms_client ().get_xmms ().coll_rename (name, new_name, Xmms.COLLECTION_NS_COLLECTIONS).notifier_set ((val) => {
				if (val.is_error ()) {
					unowned string error;
					if (val.get_error(out error)) {
						Global.get ().message ("error: %s".printf (error));
						GLib.warning ("error renaming collection: %s", error);
					}
					rename_finished (name);
				}
				name = _new_name;
				rename_finished (_new_name);
				return true;
			});
		}

		public void xmms_collection_create (string new_name) {
			Xmms.Collection collection;
			Xmms.Collection.parse (_searchquery, out collection);
			Global.get ().get_xmms_client ().get_xmms ().coll_save (collection, new_name, Xmms.COLLECTION_NS_COLLECTIONS).notifier_set ((val) => {
				if (val.is_error ()) {
					unowned string error;
					if (val.get_error(out error)) {
						Global.get ().message ("error: %s".printf (error));
						GLib.warning ("error creating collection: %s", error);
					}
				}
				stored_in_medialib = true;
				return true;
			});
		}

	}

}
